package com.ctg.behavior.client.impala;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.ctg.behavior.client.impala.common.CtQueryResult;
import com.ctg.behavior.client.impala.config.CtImpalaConfig;
import com.ctg.behavior.client.impala.config.CtImpalaMockData;
import com.ctg.behavior.client.impala.core.AbstractCtImpalaClient;
import com.ctg.behavior.client.impala.factory.CtImpalaPool;
import com.ctg.behavior.client.impala.utils.CtCalcSQLDateUtils;
import com.ctg.behavior.client.impala.utils.CtCalcSQLParserUtils;
import com.ctg.behavior.common.consts.CtFieldConsts;
import com.ctg.behavior.common.consts.CtResultConsts;

import lombok.extern.slf4j.Slf4j;

@Slf4j
@Component
public class CtImpalaClient extends AbstractCtImpalaClient {

	@Autowired
	private CtImpalaMockData impalaMockData;
	@Autowired
	private CtImpalaConfig impalaConfig;
	@Autowired
	private CtImpalaPool impalaPool;

	public CtQueryResult doQuery(String queryType, String sql) {

		CtQueryResult results = new CtQueryResult();
		results.setSql(sql);

		List<String> selectedFields = CtCalcSQLParserUtils.fetchSelectFields(sql);
		log.info("selectedFields={}", selectedFields);
		if (selectedFields.isEmpty()) {
			log.error("selectedFields is null, sql={}", sql);
			return results;
		}

		// TEMP
		if (impalaConfig.getNumDayFormat()) {
			sql = CtCalcSQLParserUtils.formatCalcSQL(sql);
			sql = CtCalcSQLDateUtils.sqlDate2NumDate(sql);
		}
		log.info("sql(t)={}", sql);

		// 若是模拟测试，则不连接真实Impala
		if (!impalaConfig.getLanuch()) {
			List<Map<String, Object>> mockDatas = impalaMockData.getMockDatas().get(queryType);
			if (null == mockDatas) {
				return results;
			}
			for (Map<String, Object> mapData : mockDatas) {
				LinkedHashMap<String, Object> linkedMapOneRecord = new LinkedHashMap<>();
				for (String oneField : selectedFields) {
					Object value = mapData.get(oneField);
					if (null == value && oneField.startsWith("$")) {
						oneField = oneField.substring(1);
						value = mapData.get(oneField);
					}
					if (impalaConfig.getNumDayFormat() && CtFieldConsts.FIELD_KEY_EVENT_DATE.equals(oneField)) {
						value = CtCalcSQLDateUtils.toStdDate(value.toString());
					}
					linkedMapOneRecord.put(oneField, value);
				}
				results.getRows().add(linkedMapOneRecord);
			}

			return results;
		}

		Connection impalaConnection = null;
		try {
			impalaConnection = impalaPool.openConnection();
			PreparedStatement ps = impalaConnection.prepareStatement(sql);
			ResultSet resultSet = ps.executeQuery();
			while (resultSet.next()) {
				LinkedHashMap<String, Object> oneRecord = new LinkedHashMap<>();
				for (String field : selectedFields) {
					String value = resultSet.getString(field);
					if (impalaConfig.getNumDayFormat() && CtFieldConsts.FIELD_KEY_EVENT_DATE.equals(field)) {
						value = CtCalcSQLDateUtils.toStdDate(value);
					}
					oneRecord.put(field, value);
				}
				results.getRows().add(oneRecord);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			results.setCode(CtResultConsts.RET_FAIL_SQL);
			results.setMsg("请求参数异常!");
		} finally {
			impalaPool.closeConnection(impalaConnection);
		}

		return results;
	}

}
